/**
 * Browser Informations and Capabilities Detection
 *
 * @author  nasca iacob
 * @version 1.0.0
 * 
 */
namespace("jclass.browser")
({
    Browser : jClass({
         public : {
            userAgent : '',
            name : 'unknown',
            os : 'unknown',
            version : 'unknown',
            language : navigator.language? navigator.language : navigator.userLanguage,
            GMT : -(new Date().getTimezoneOffset() / 60), 
            quirksMode : false,

            screen : {
               width : screen.width,
               height : screen.height,
               availableWidth : screen.availWidth,
               availableHeight : screen.availHeight,
               bitDepth : screen.colorDepth
            },

            capabilities : {
                activex : false,
                acrobat : false,
                audio : false,
                borderRadius : false,
                canvas : false,
                canvasText : false,
                contextMenu : false,
                crossWindowMessaging : false,
                cssGradient : false,
                dragAndDrop : false,
                fontface : false,
                geoLocation : false,
                gears : false,
                hashChangeEvent : false,
                historyManagement : false,
                indexedDB : false,
                localStorage : false,
                multipleBackgrounds : false,
                rgba : false,
                realPlayer : false,
                quickTime : false,
                sessionStorage : false,
                silverlight : false,
                flash : false,
                java : false,
                svg : false,
                video : false,
                webSQL : false,
                webSocket : false,
                workers : false
            }
        },
        constructor : function() {
            this.userAgent = navigator.userAgent.toLowerCase();
            this.name = searchString(dataBrowser);
            this.version = searchVersion(navigator.userAgent) || searchVersion(navigator.appVersion) || "an unknown version";
            this.os = searchString(dataOS) || "an unknown OS";
            // browser is running in quirks mode
            this.quirksMode = testQuirksMode();
            // Test capabilites
            this.capabilities.activex = testActiveX();
            this.capabilities.acrobat = testPlugins('acrobat');
            this.capabilities.audio = testAudio();
            this.capabilities.borderRadius = testBorderRadius();
            this.capabilities.canvas = testCanvas();
            this.capabilities.canvasText = !!(testCanvas() && typeof document.createElement('canvas').getContext('2d').fillText == 'function');
            this.capabilities.contextMenu = testContextMenu();
            this.capabilities.crossWindowMessaging = !!navigator.postMessage;
            this.capabilities.cssGradient = testCssGradients();
            this.capabilities.dragAndDrop = testDrangAndDrop();
            this.capabilities.fontface = testFontFace();
            this.capabilities.geoLocation = !!navigator.geolocation;
            this.capabilities.gears = testPlugins('gears');
            this.capabilities.hashChangeEvent = testHashChangeEvent();
            this.capabilities.historyManagement = !!(window.history && history.pushState);
            this.capabilities.indexedDB = !!window['indexedDB'];
            this.capabilities.localStorage = ('localStorage' in window) && window['localStorage'] !== null;
            this.capabilities.multipleBackgrounds = testMultipleBackgrounds();
            this.capabilities.rgba = testRGBA();
            this.capabilities.realPlayer = testPlugins('real');
            this.capabilities.quickTime = testPlugins('quick');
            this.capabilities.sessionStorage = ('sessionStorage' in window) && window['sessionStorage'] !== null;
            this.capabilities.svg = !!document.createElementNS && !!document.createElementNS( "http://www.w3.org/2000/svg", "svg").createSVGRect;
            this.capabilities.java = testPlugins('java');
            this.capabilities.silverlight = testPlugins('silverlight');
            this.capabilities.flash = testPlugins('flash');
            this.capabilities.video = testVideo();
            this.capabilities.webSQL = testWebSql();
            this.capabilities.webSocket = ('WebSocket' in window);
            this.capabilities.workers = !!window.Worker;
        },
        private : {
            searchString : function (data) { for (var i=0;i<data.length;i++) { var dataString = data[i].string;
              var dataProp = data[i].prop; var versionSearchString = data[i].versionSearch || data[i].identity;
              if (dataString) { if (dataString.indexOf(data[i].subString) != -1) return data[i].identity; }
              else if (dataProp) return data[i].identity; }
            },

            searchVersion : function (dataString) { var index = dataString.indexOf(this.versionSearchString);
                if (index == -1) return; return parseFloat(dataString.substring(index + this.versionSearchString.length + 1));
            },            
            dataBrowser : [
                {string: navigator.userAgent, subString: "Chrome", identity: "Chrome"},
                {string: navigator.userAgent, subString: "OmniWeb", versionSearch: "OmniWeb/", identity: "OmniWeb"},
                {string: navigator.vendor, subString: "Apple", identity: "Safari", versionSearch: "Version"},
                {prop: window.opera, identity: "Opera"},
                {string: navigator.vendor, subString: "iCab", identity: "iCab"},
                {string: navigator.vendor, subString: "KDE", identity: "Konqueror"},
                {string: navigator.userAgent, subString: "Firefox", identity: "Firefox"},
                {string: navigator.vendor, subString: "Camino", identity: "Camino"},
                {string: navigator.userAgent, subString: "Netscape", identity: "Netscape"},
                {string: navigator.userAgent, subString: "MSIE", identity: "IE", versionSearch: "MSIE"},
                {string: navigator.userAgent, subString: "Gecko", identity: "Mozilla", versionSearch: "rv"},
                {string: navigator.userAgent, subString: "Mozilla", identity: "Netscape", versionSearch: "Mozilla"}
            ],
            dataOS : [
                {string: navigator.platform, subString: "Win", identity: "Windows"},
                {string: navigator.platform, subString: "Mac", identity: "Mac"},
                {string: navigator.userAgent, subString: "iPhone", identity: "iPhone/iPod"},
                {string: navigator.platform, subString: "Linux", identity: "Linux"}
            ],
            isEventSupported : function(eventName, element) {
                 element = element === undefined ?  document.createElement("div") : element;
                 eventName = 'on' + eventName; var isSupported = (eventName in element);
                 if (!isSupported && element.setAttribute) {element.setAttribute(eventName, 'return;');
                 isSupported = typeof element[eventName] == 'function'; } element = null; return isSupported;
            },
            testQuirksMode : function () {
                if (document.createElement) { var el = document.createElement("div"); if (el && el.style) {
                el.style.width = "1"; } return (el.style.width === "1px"); }
            },
            testPlugins : function(name) {
                var tmp = {};
                for (var i = 0; i < navigator.plugins.length; i++) {
                    var plugin = navigator.plugins[i];
                    if (plugin.name && plugin.name.match(new RegExp(name, 'i'))) {
                        tmp.version = plugin.version;
                        tmp.enabled = true;
                        return tmp;
                    }
                }
                return false;
            },
            testVideo : function() {
                var elem = document.createElement('video'), bool = !!elem['canPlayType'];
                if (bool){ bool = new Boolean(bool);
                bool.ogg  = elem['canPlayType']('video/ogg; codecs="theora"') !== "";
                bool.h264 = elem['canPlayType']('video/mp4; codecs="avc1.42E01E"') !== "";
                bool.webm = elem['canPlayType']('video/webm; codecs="vp8, vorbis"') !== ""; }
                return bool;
            },
            testAudio : function() {
                 var elem = document.createElement('audio'), bool = !!elem['canPlayType'];
                 if (bool){ bool = new Boolean(bool);
                 bool.ogg  = elem['canPlayType']('audio/ogg; codecs="vorbis"') !== "";
                 bool.mp3  = elem['canPlayType']('audio/mpeg;') !== "";
                 bool.wav  = elem['canPlayType']('audio/wav; codecs="1"') !== "";
                 bool.m4a  = (elem['canPlayType']('audio/x-m4a;') || elem['canPlayType']('audio/aac;'))  !== "";}
                 return bool;
            },
            testFontFace : function() { // @font-face detection routine created by Paul Irish
                var doc = document, docElement = doc.documentElement,fontret,ret = {};
                if (/*@cc_on@if(@_jscript_version>=5)!@end@*/0) { fontret = true; }
                else { var st  = doc.createElement('style'), spn = doc.createElement('span'),
                size, isFakeBody = false, body = doc.body, callback, isCallbackCalled;
                st.textContent = "@font-face{font-family:testfont;src:url('data:font/ttf;base64,AAEAAAAMAIA"+
                "AAwBAT1MvMliohmwAAADMAAAAVmNtYXCp5qrBAAABJAAAANhjdnQgACICiAAAAfwAAAAEZ2FzcP//AAMAAAIAAAAACG"+
                "dseWYv5OZoAAACCAAAANxoZWFk69bnvwAAAuQAAAA2aGhlYQUJAt8AAAMcAAAAJGhtdHgGDgC4AAADQAAAABRsb2NhAI"+
                "QAwgAAA1QAAAAMbWF4cABVANgAAANgAAAAIG5hbWUgXduAAAADgAAABPVwb3N03NkzmgAACHgAAAA4AAECBAEsAAUAAAK"+
                "ZAswAAACPApkCzAAAAesAMwEJAAACAAMDAAAAAAAAgAACbwAAAAoAAAAAAAAAAFBmRWQAAAAgqS8DM/8zAFwDMwDNAAAA"+
                "BQAAAAAAAAAAAAMAAAADAAAAHAABAAAAAABGAAMAAQAAAK4ABAAqAAAABgAEAAEAAgAuqQD//wAAAC6pAP///9ZXAwAAA"+
                "AAAAAACAAAABgBoAAAAAAAvAAEAAAAAAAAAAAAAAAAAAAABAAIAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"+
                "AAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEACoAAAAGAAQAAQACAC6pAP//AAAALqkA///"+
                "/1lcDAAAAAAAAAAIAAAAiAogAAAAB//8AAgACACIAAAEyAqoAAwAHAC6xAQAvPLIHBADtMrEGBdw8sgMCAO0yALEDAC88"+
                "sgUEAO0ysgcGAfw8sgECAO0yMxEhESczESMiARDuzMwCqv1WIgJmAAACAFUAAAIRAc0ADwAfAAATFRQWOwEyNj0BNCYrA"+
                "SIGARQGKwEiJj0BNDY7ATIWFX8aIvAiGhoi8CIaAZIoN/43KCg3/jcoAWD0JB4eJPQkHh7++EY2NkbVRjY2RgAAAAABAE"+
                "H/+QCdAEEACQAANjQ2MzIWFAYjIkEeEA8fHw8QDxwWFhwWAAAAAQAAAAIAAIuYbWpfDzz1AAsEAAAAAADFn9IuAAAAAMW"+
                "f0i797/8zA4gDMwAAAAgAAgAAAAAAAAABAAADM/8zAFwDx/3v/98DiAABAAAAAAAAAAAAAAAAAAAABQF2ACIAAAAAAVUA"+
                "AAJmAFUA3QBBAAAAKgAqACoAWgBuAAEAAAAFAFAABwBUAAQAAgAAAAEAAQAAAEAALgADAAMAAAAQAMYAAQAAAAAAAACLA"+
                "AAAAQAAAAAAAQAhAIsAAQAAAAAAAgAFAKwAAQAAAAAAAwBDALEAAQAAAAAABAAnAPQAAQAAAAAABQAKARsAAQAAAAAABg"+
                "AmASUAAQAAAAAADgAaAUsAAwABBAkAAAEWAWUAAwABBAkAAQBCAnsAAwABBAkAAgAKAr0AAwABBAkAAwCGAscAAwABBAk"+
                "ABABOA00AAwABBAkABQAUA5sAAwABBAkABgBMA68AAwABBAkADgA0A/tDb3B5cmlnaHQgMjAwOSBieSBEYW5pZWwgSm9o"+
                "bnNvbi4gIFJlbGVhc2VkIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgT3BlbiBGb250IExpY2Vuc2UuIEtheWFoIExpIGdse"+
                "XBocyBhcmUgcmVsZWFzZWQgdW5kZXIgdGhlIEdQTCB2ZXJzaW9uIDMuYmFlYzJhOTJiZmZlNTAzMiAtIHN1YnNldCBvZi"+
                "BKdXJhTGlnaHRiYWVjMmE5MmJmZmU1MDMyIC0gc3Vic2V0IG9mIEZvbnRGb3JnZSAyLjAgOiBKdXJhIExpZ2h0IDogMjM"+
                "tMS0yMDA5YmFlYzJhOTJiZmZlNTAzMiAtIHN1YnNldCBvZiBKdXJhIExpZ2h0VmVyc2lvbiAyIGJhZWMyYTkyYmZmZTUw"+
                "MzIgLSBzdWJzZXQgb2YgSnVyYUxpZ2h0aHR0cDovL3NjcmlwdHMuc2lsLm9yZy9PRkwAQwBvAHAAeQByAGkAZwBoAHQAI"+
                "AAyADAAMAA5ACAAYgB5ACAARABhAG4AaQBlAGwAIABKAG8AaABuAHMAbwBuAC4AIAAgAFIAZQBsAGUAYQBzAGUAZAAgAH"+
                "UAbgBkAGUAcgAgAHQAaABlACAAdABlAHIAbQBzACAAbwBmACAAdABoAGUAIABPAHAAZQBuACAARgBvAG4AdAAgAEwAaQB"+
                "jAGUAbgBzAGUALgAgAEsAYQB5AGEAaAAgAEwAaQAgAGcAbAB5AHAAaABzACAAYQByAGUAIAByAGUAbABlAGEAcwBlAGQA"+
                "IAB1AG4AZABlAHIAIAB0AGgAZQAgAEcAUABMACAAdgBlAHIAcwBpAG8AbgAgADMALgBiAGEAZQBjADIAYQA5ADIAYgBmA"+
                "GYAZQA1ADAAMwAyACAALQAgAHMAdQBiAHMAZQB0ACAAbwBmACAASgB1AHIAYQBMAGkAZwBoAHQAYgBhAGUAYwAyAGEAOQ"+
                "AyAGIAZgBmAGUANQAwADMAMgAgAC0AIABzAHUAYgBzAGUAdAAgAG8AZgAgAEYAbwBuAHQARgBvAHIAZwBlACAAMgAuADA"+
                "AIAA6ACAASgB1AHIAYQAgAEwAaQBnAGgAdAAgADoAIAAyADMALQAxAC0AMgAwADAAOQBiAGEAZQBjADIAYQA5ADIAYgBm"+
                "AGYAZQA1ADAAMwAyACAALQAgAHMAdQBiAHMAZQB0ACAAbwBmACAASgB1AHIAYQAgAEwAaQBnAGgAdABWAGUAcgBzAGkAb"+
                "wBuACAAMgAgAGIAYQBlAGMAMgBhADkAMgBiAGYAZgBlADUAMAAzADIAIAAtACAAcwB1AGIAcwBlAHQAIABvAGYAIABKAH"+
                "UAcgBhAEwAaQBnAGgAdABoAHQAdABwADoALwAvAHMAYwByAGkAcAB0AHMALgBzAGkAbAAuAG8AcgBnAC8ATwBGAEwAAAA"+
                "AAgAAAAAAAP+BADMAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAQACAQIAEQt6ZXJva2F5YWhsaQ==')}";
                document.getElementsByTagName('head')[0].appendChild(st);
                spn.setAttribute('style','font:99px _,arial,helvetica;position:absolute;visibility:hidden');
                if  (!body){ body = docElement.appendChild(document.createElement('fontface')); isFakeBody = true; }
                spn.innerHTML = '........'; spn.id = 'fonttest'; body.appendChild(spn);
                size = spn.offsetWidth*spn.offsetHeight; spn.style.font = '99px testfont,_,arial,helvetica';
                fontret = size !== spn.offsetWidth*spn.offsetHeight; function delayedCheck(){
                if (!body.parentNode) return; fontret = ret['fontface'] = size !== spn.offsetWidth*spn.offsetHeight;
                docElement.className = docElement.className.replace(/(no-)?fontface\b/,'') + (fontret ?' ':' no-')+'fontface';
                } setTimeout(delayedCheck,75); setTimeout(delayedCheck,75*2);
                addEventListener('load',function(){delayedCheck();(isCallbackCalled = true) && callback && callback(fontret);
                setTimeout(function(){if (!isFakeBody) body = spn;body.parentNode.removeChild(body);st.parentNode.removeChild(st);
                }, 50);},false);}ret._fontfaceready = function(fn){(isCallbackCalled || fontret) ? fn(fontret) : (callback = fn);}
                return fontret || size !== spn.offsetWidth;
            },
            testCssGradients : function() {
                var doc = document.createElement("div"), prefixes = ' -o- -moz- -ms- -webkit- -khtml- '.split(' '),
                str1 = 'background-image:', str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));',
                str3 = 'linear-gradient(left top,#9f9, white);'; doc.style.cssText = (str1 + prefixes.join(str2 + str1) +
                prefixes.join(str3 + str1)).slice(0, -str1.length);
                return ('' + doc.style.backgroundImage).indexOf('gradient') !== -1;
            },
            testBorderRadius : function() {
                var docEl = document.documentElement, s;
                if (docEl && (s = docEl.style)) { return typeof s.borderRadius == "string" ||
                typeof s.MozBorderRadius == "string" || typeof s.WebkitBorderRadius == "string" ||
                typeof s.KhtmlBorderRadius == "string"; } return false;
            },
            testRGBA : function() {
                var result = null; if (document.createElement) {
                var value = "rgba(1,1,1,0.5)", el = document.createElement("p"), re = /^rgba/;
                if (el && el.style && typeof re.test == "function") { try { el.style.color = value;
                result = re.test(el.style.color); } catch (e) { result = false; }}} return result;
            },
            testMultipleBackgrounds : function() {
                var d = document.createElement("div");d.style.cssText = 'background:url(//:),url(//:),red url(//:)';
                return new RegExp("(url\\s*\\(.*?){3}").test(d.style['background']);
            },
            testContextMenu : function() {
                var isPresent = null; if (document.createElement) { var el = document.createElement("p");
                if (el && el.setAttribute) { el.setAttribute("oncontextmenu", "");
                isPresent = typeof el.oncontextmenu != "undefined"; }} return isPresent;
            },
            testCanvas : function() {
                if (document.createElement) { var elCanvas = document.createElement("canvas");
                return !!(elCanvas && elCanvas.getContext && elCanvas.getContext("2d"));} return false;
            },
            testActiveX : function() {
                if (typeof ActiveXObject == "undefined") { return false; }
                var xmlVersions = ["Microsoft.XMLHTTP", "Msxml2.XMLHTTP.3.0", "Msxml2.XMLHTTP.4.0", "Msxml2.XMLHTTP.5.0",
                "Msxml2.XMLHTTP.6.0"]; for(var i = xmlVersions.length; i--;) { try{ if(new ActiveXObject(xmlVersions[i]))
                { return true; }} catch (ex) {}} return false;
            },
            testWebSql : function() {
                var result = !!window.openDatabase; if (result){ try { result = !!openDatabase("testdb",
                "1.0", "html5 test db", 200000);} catch(err) { result = false; }}return result;
            },
            testHashChangeEvent : function() {
                return isEventSupported('hashchange', window) && ( document.documentMode === undefined || document.documentMode > 7 );
            },
            testDrangAndDrop : function() {
                return isEventSupported('drag') && isEventSupported('dragstart') && isEventSupported('dragenter')
                && isEventSupported('dragover') && isEventSupported('dragleave') && isEventSupported('dragend')
                && isEventSupported('drop');
            }
        }
    })
});